//      mpi_helper.h
//      
//      Copyright 2012 tqlong <tqlong@espada>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.

#ifndef MPI_HELPER_ONLY_H
#define MPI_HELPER_ONLY_H

#include <boost/mpi.hpp>
#include "arma_helper.h"

namespace mpi = boost::mpi;

namespace boost {
  namespace serialization {
    template<typename A>
    void serialize(A& a, vec_t& v, const unsigned int version) {
      if (A::is_saving::value) {
	int n = sz(v);
	a & n;
	for (int i = 0; i < sz(v); i++) {
	  double v_i = v(i); 
	  a & v_i; 
	}
      }
      else if (A::is_loading::value) {
	int n;
	a & n;
	v.set_size(n);
	for (int i = 0; i < n; i++) {
	  double v_i;
	  a & v_i;
	  v(i) = v_i;
	}
      }
    }

    template<typename A>
    void serialize(A& a, matrix_t& M, const unsigned int version) {
      if (A::is_saving::value) {
	int m = M.n_rows, n = M.n_cols;
	a & m;
	a & n;
	for (int i = 0; i < m; i++) 
	  for (int j = 0; j < n; j++) {
	    double v_i = M(i,j); 
	    a & v_i; 
	  }
      }
      else if (A::is_loading::value) {
	int m, n;
	a & m;
	a & n;
	M.set_size(m, n);
	for (int i = 0; i < m; i++) 
	  for (int j = 0; j < n; j++) {
	    double v_i;
	    a & v_i;
	    M(i,j) = v_i;
	  }
      }
    }

  }
}

namespace boost { namespace mpi {
    template<>
      struct is_commutative<std::plus<double>, double> : mpl::true_ { };
    template<>
      struct is_commutative<std::plus<vec_t>, vec_t> : mpl::true_ { };
    template<>
      struct is_commutative<std::plus<matrix_t>, matrix_t> : mpl::true_ { };
} } // end namespace boost::mpi
#endif
